home *** CD-ROM | disk | FTP | other *** search
- /*
- File: ComponentDispatch.c
-
- Contains: Common routines for dispatching for any sound component
-
- Written by: Mark Cookson
-
- Copyright: Copyright © 1996-1999 by Apple Computer, Inc., All Rights Reserved.
-
- You may incorporate this Apple sample source code into your program(s) without
- restriction. This Apple sample source code has been provided "AS IS" and the
- responsibility for its operation is yours. You are not permitted to redistribute
- this Apple sample source code as "Apple sample source code" after having made
- changes. If you're going to re-distribute the source, we require that you make
- it clear in the source that the code was descended from Apple sample source
- code, but that you've made changes.
-
- Change History (most recent first):
- 8/13/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1
-
-
- */
-
- #include "ComponentDispatch.h"
- #include <Gestalt.h>
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // Sound Component Entry Point
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- #if GENERATINGPOWERPC
- ProcInfoType __procinfo=uppSoundComponentEntryPointProcInfo;
- #endif
- pascal ComponentResult main(ComponentParameters *params, SoundComponentGlobalsPtr globals)
- {
- ComponentResult result;
- short selector = params->what;
-
- if (selector < 0)
- switch (selector - kComponentRegisterSelect) // standard component selectors
- {
- case kComponentRegisterSelect - kComponentRegisterSelect:
- result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentRegister);
- break;
-
- case kComponentVersionSelect - kComponentRegisterSelect:
- return (kSoundComponentVersion);
- break;
-
- case kComponentCanDoSelect - kComponentRegisterSelect:
- result = __SoundComponentCanDo(0, *((short *) ¶ms->params[0]));
- break;
-
- case kComponentCloseSelect - kComponentRegisterSelect:
- result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentClose);
- break;
-
- case kComponentOpenSelect - kComponentRegisterSelect:
- result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentOpen);
- break;
-
- default:
- result = badComponentSelector;
- break;
- }
- else if (selector < kDelegatedSoundComponentSelectors) // selectors that cannot be delegated
- switch (selector)
- {
- case kSoundComponentSetSourceSelect:
- result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentSetSource);
- break;
-
- case kSoundComponentGetSourceDataSelect:
- result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentGetSourceData);
- break;
-
- case kSoundComponentSetOutputSelect:
- result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentSetOutput);
- break;
-
- default:
- result = badComponentSelector;
- break;
- }
- else // selectors that can be delegated
- switch (selector)
- {
- case kSoundComponentGetInfoSelect:
- result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentGetInfo);
- break;
-
- case kSoundComponentStopSourceSelect:
- result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentStopSource);
- break;
-
- case kSoundComponentPlaySourceBufferSelect:
- result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentPlaySourceBuffer);
- break;
-
- default:
- result = DelegateComponentCall(params, globals->sourceComponent);
- break;
- }
-
- return (result);
- }
-
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static pascal ComponentResult __SoundComponentCanDo(void *unused1, short selector)
- {
- #pragma unused (unused1)
-
- ComponentResult result;
-
- switch (selector)
- {
- case kComponentRegisterSelect:
- case kComponentVersionSelect:
- case kComponentCanDoSelect:
- case kComponentCloseSelect:
- case kComponentOpenSelect:
- case kSoundComponentSetSourceSelect:
- case kSoundComponentGetSourceSelect:
- case kSoundComponentGetSourceDataSelect:
- case kSoundComponentSetOutputSelect:
- // selectors that can be delegated
- case kSoundComponentGetInfoSelect:
- case kSoundComponentStopSourceSelect:
- case kSoundComponentPlaySourceBufferSelect:
- result = true;
- break;
-
- default:
- result = false;
- break;
- }
-
- return (result);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // Component Manager Methods
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- /* ==============================================================================
- Component Open
-
- This routine is called when the Component Manager creates an instance of this
- component. The routine should allocate global variables in the appropriate heap
- and call SetComponentInstanceStorage() so the Component Manager can remember
- the globals and pass them to all the method calls.
-
- Determining the heap to use can be tricky. The Component Manager will normally
- load the component code into the system heap, which is good, since many applications
- will be sharing this component to play sound. In this case, the components's global
- variable storage should also be created in the system heap.
-
- However, if system heap memory is tight, the Component Manager will load
- the component into the application heap of the first application that plays sound.
- When this happens, the component should create global storage in the application heap
- instead. The Sound Manager will make sure that other applications will not try
- to play sound while the component is in this application heap.
-
- To determine the proper heap to use, call GetComponentInstanceA5(). If the value
- returned is 0, then the component was loaded into the system heap, and all storage
- should be allocated there. If the value returned is non-zero, the component is in
- the application heap specifed by returned A5 value, and all storage should be
- allocated in this application heap.
-
- NOTE: If the component is loaded into the application heap, the value returned by
- GetComponentRefCon() will be 0.
- NOTE: Do not attempt to initialize in this call, since the Component Manager will
- call Open() BEFORE calling Register().
- NOTE: This routine is never called at interrupt time.
- ============================================================================== */
-
- pascal ComponentResult __SoundComponentOpen(void *unused1, ComponentInstance self)
- {
- #pragma unused (unused1)
-
- Handle h;
- SoundComponentGlobalsPtr globals;
-
- h = NewHandleClear(sizeof(SoundComponentGlobals)); // get space for globals
- if (h == nil)
- return(MemError());
-
- HLock(h);
- globals = (SoundComponentGlobalsPtr) *h;
- SetComponentInstanceStorage (self, (Handle) globals); // save pointer to our globals
-
- globals->globalsHandle = h; // remember the handle
- globals->thisComponent.format = kOutputSampleFormat; // output sample format
- globals->thisComponent.sampleSize = kOutputSampleSize; // output sample size
- globals->outputSamples = kMaxOutputSamples; // size of our output buffer
-
- return (noErr);
- }
-
- /* ==============================================================================
- Component Close
-
- This routine is called when the Component Manager is closing the instance of
- this component. It should delete all global storage and close any other components
- that were opened.
-
- NOTE: Be sure to check that the globals pointer passed in to this routine is
- not set to NIL. If the Open() routine fails for any reason, the Component
- Manager will call this routine passing in a NIL for the globals.
- NOTE: This routine is never called at interrupt time.
- ============================================================================== */
-
- pascal ComponentResult __SoundComponentClose(SoundComponentGlobalsPtr globals, ComponentInstance self)
- {
- #pragma unused (self)
-
- if (globals) // we have some globals
- {
- if (globals->sourceComponent) // we have a source component
- CloseComponent(globals->sourceComponent); // close it
-
- globals->thisComponent.sampleCount = 0; // nothing in our buffer now
- DisposeHandle(globals->globalsHandle); // dispose our storage
- }
-
- return (noErr);
- }
-
- /* ==============================================================================
- Component Register
-
- This routine is called once, usually at boot time, when the Component Manager
- is first registering this sound component. This routine should check to see if the proper
- Sound Manager is installed and return 0 if it is. If the right Sound Manager is not
- installed, the routine should return 1 and this component will not be registered.
-
- NOTE: The cmpWantsRegisterMessage bit must be set in the component flags of the
- sound component in order for this routine to be called.
- NOTE: This routine is never called at interrupt time.
- ============================================================================== */
-
- pascal ComponentResult __SoundComponentRegister(SoundComponentGlobalsPtr globals)
- {
- #pragma unused (globals)
-
- long result;
- NumVersion version;
-
- if ((Gestalt(gestaltSoundAttr, &result) == noErr) && // snd gestalt is available
- (result & (1L << gestaltSoundIOMgrPresent))) // snd dispatcher is available
- {
- version = SndSoundManagerVersion(); // get the Sound Manager version
- if (version.majorRev >= kRequiredSndMgrMajorRev) // it's what we need
- {
- return (0); // install this compression component
- }
- }
-
- return (1); // do not install component
- }
-
- /* ==============================================================================
- GetInfo
-
- This routine returns information about this output component to the Sound Manager.
- A 4-byte OSType selector is used to determine the type and size of the information
- to return. If the component does not support a selector, it should delegate this
- call on up the chain.
-
- NOTE: This can be called at interrupt time. However, selectors that return
- a handle will not be called at interrupt time.
- ============================================================================== */
-
- pascal ComponentResult __SoundComponentGetInfo(SoundComponentGlobalsPtr globals, SoundSource sourceID,
- OSType selector, void *infoPtr)
- {
- ComponentResult result = noErr;
-
- switch (selector)
- {
- case siCompressionFactor:
- GetCompressorInfo(infoPtr); // fill out the CompressionInfo structure passed in
- break;
-
- default:
- result = SoundComponentGetInfo(globals->sourceComponent, sourceID, selector, infoPtr);
- break;
- }
-
- return (result);
- }
-
- /* ==============================================================================
- StopSource
-
- This routine is used to stop sounds that are currently playing. It should
- clear out any internal buffers, reset any compression state information
- and then delegate the call up the chain.
-
- NOTE: This can be called at interrupt time.
- ============================================================================== */
-
- pascal ComponentResult __SoundComponentStopSource(SoundComponentGlobalsPtr globals, short count, SoundSource *sources)
- {
- globals->sourceDataPtr = nil; // clear out internal buffers
- globals->thisComponent.sampleCount = 0; // our buffer is empty
- #ifdef COMPRESSION
- InitializeCompressor(globals); // initialize our compressor state
- #else
- InitializeDecompressor(globals); // initialize our compressor state
- #endif
- return (SoundComponentStopSource(globals->sourceComponent, count, sources)); // delegate this call
- }
-
- /* ==============================================================================
- PlaySourceBuffer
-
- This routine is used to start a new sound playing. It should clear out any internal buffers
- but should NOT reset any compression state information, since this could be a
- continuation of a sound that has been broken into pieces. Then the call should be
- delegated up the chain.
-
- NOTE: This can be called at interrupt time.
- ============================================================================== */
-
- pascal ComponentResult __SoundComponentPlaySourceBuffer(SoundComponentGlobalsPtr globals, SoundSource sourceID, SoundParamBlockPtr pb, long actions)
- {
- globals->sourceDataPtr = nil; // clear out internal buffers
- globals->thisComponent.sampleCount = 0; // our buffer is empty
-
- return (SoundComponentPlaySourceBuffer(globals->sourceComponent, sourceID, pb, actions)); // delegate this call
- }
-
-